<?php

namespace app\components;

use Yii;
use app\components\oauth2\repositories\AccessTokenRepository;
use app\components\oauth2\repositories\UserRepository;
use app\components\oauth2\repositories\AuthCodeRepository;
use app\components\oauth2\repositories\ClientRepository;
use app\components\oauth2\repositories\RefreshTokenRepository;
use app\components\oauth2\repositories\ScopeRepository;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Grant\AuthCodeGrant;
use League\OAuth2\Server\Grant\PasswordGrant;
use League\OAuth2\Server\Grant\RefreshTokenGrant;
use yii\di\Instance;

class AuthorizationServerInstance
{
    /** @var AuthorizationServer */
    public $server;

    public function __construct($server)
    {
        $this->server = $server;
    }

    /**
     * @return AuthorizationServer
     * @throws \yii\base\InvalidConfigException
     */
    public static function getTotal()
    {
        if (!Yii::$container->has(self::class)) {
            $server = new AuthorizationServer(
                new ClientRepository(),
                new AccessTokenRepository(),
                new ScopeRepository(),
                new CryptKey(Yii::$app->getBasePath() . \Yii::$app->params['oauth2']['private_key_path'], null, false),
                \Yii::$app->params['oauth2']['encryption_key']
            );

            $accessTokenTTL = new \DateInterval('PT2H');
            $refreshTokenTTL = new \DateInterval('P1M');

            $passwordGrant = new PasswordGrant(
                new UserRepository(),           // instance of UserRepositoryInterface
                new RefreshTokenRepository()    // instance of RefreshTokenRepositoryInterface
            );
            $passwordGrant->setRefreshTokenTTL($refreshTokenTTL); // refresh tokens will expire after 1 month

            $refreshTokenGrant = new RefreshTokenGrant(new RefreshTokenRepository());
            $refreshTokenGrant->setRefreshTokenTTL($refreshTokenTTL); // refresh tokens will expire after 1 month

            $authCodeGrant = new AuthCodeGrant(
                new AuthCodeRepository(),
                new RefreshTokenRepository(),
                new \DateInterval('PT10M')
            );

            $authCodeGrant->setRefreshTokenTTL($refreshTokenTTL);
            // Enable the password grant on the server with a token TTL of 1 hour
            $server->enableGrantType(
                $passwordGrant,
                $accessTokenTTL // access tokens will expire after 1 hour
            );

            $server->enableGrantType(
                $refreshTokenGrant,
                $accessTokenTTL // access tokens will expire after 1 hour
            );

            $server->enableGrantType(
                $authCodeGrant,
                $accessTokenTTL
            );
            Yii::$container->setSingleton(self::class, [
                'class' => self::class,
                'server' => $server
            ]);
        }
        /** @var  $instance self */
        $instance = Instance::ensure(self::class);
        return $instance->server;
    }

    public function set($new_val)
    {
        $this->server = $new_val;
        return $this;
    }
}
